import pandas as pd
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.gridspec import GridSpec
import matplotlib.ticker as ticker
import matplotlib.font_manager as fm

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


# 创建模拟数据集
def generate_mock_data():
    # 公司基本信息
    companies = ['公司A', '公司B', '公司C']
    business_lines = ['人身险', '财险', '再保人身险']

    # 时间范围：2024Q4（基期）和 2025Q1（报告期）
    periods = ['2024Q4', '2025Q1']

    # 生成模拟数据
    np.random.seed(42)
    data = []
    for period in periods:
        for company in companies:
            for line in business_lines:
                # 基础保费数据
                base_premium = np.random.uniform(1e6, 1e7)
                ceded_premium = base_premium * np.random.uniform(0.1, 0.3)
                net_premium = base_premium - ceded_premium

                # 人身险特有数据
                first_year_premium = base_premium * np.random.uniform(0.4, 0.7) if '人身' in line else 0
                std_premium = first_year_premium * np.random.uniform(0.8, 1.2) if '人身' in line else 0

                # 续保率相关
                start_policies = np.random.randint(10000, 50000)
                end_policies = int(start_policies * np.random.uniform(0.85, 0.95)) if '人身' in line else 0

                # 营销渠道数据
                sales_count = np.random.randint(500, 2000)
                new_policies = np.random.randint(1000, 5000)

                # 财务数据
                equity = np.random.uniform(5e7, 2e8)

                data.append({
                    '报告期': period,
                    '公司': company,
                    '业务线': line,
                    '原保费收入': base_premium,
                    '分出保费': ceded_premium,
                    '自留保费': net_premium,
                    '首年保费': first_year_premium,
                    '标准保费': std_premium,
                    '期初保单数': start_policies,
                    '期末保单数': end_policies,
                    '营销员数量': sales_count,
                    '新单件数': new_policies,
                    '所有者权益': equity
                })

    return pd.DataFrame(data)


# 核心指标计算函数
def calculate_metrics(df):
    # 准备市场总量数据（模拟）
    market_total = df.groupby(['报告期', '业务线'])['原保费收入'].sum().reset_index()
    market_total = market_total.rename(columns={'原保费收入': '市场总保费'})

    # 合并市场数据
    df = pd.merge(df, market_total, on=['报告期', '业务线'])

    # 分离基期和报告期数据
    base_df = df[df['报告期'] == '2024Q4'].copy().add_suffix('_base')
    report_df = df[df['报告期'] == '2025Q1'].copy().add_suffix('_report')

    # 重命名关键列以便合并
    base_df = base_df.rename(columns={'公司_base': '公司', '业务线_base': '业务线'})
    report_df = report_df.rename(columns={'公司_report': '公司', '业务线_report': '业务线'})

    # 合并两个时期的数据
    merged = pd.merge(report_df, base_df, on=['公司', '业务线'], how='left')

    # 计算指标
    results = []
    for _, row in merged.iterrows():
        # 1. 原/分保费收入增长率
        premium_base = row.get('原保费收入_base', 0)
        premium_report = row.get('原保费收入_report', 0)
        premium_growth = ((premium_report - premium_base) / premium_base * 100
                          if premium_base > 0 else 0)

        # 2. 自留保费增长率
        net_premium_base = row.get('自留保费_base', 0)
        net_premium_report = row.get('自留保费_report', 0)
        net_premium_growth = ((net_premium_report - net_premium_base) / net_premium_base * 100
                              if net_premium_base > 0 else 0)

        # 3. 原保费收入市场份额
        market_share = (premium_report / row.get('市场总保费_report', 1) * 100
                        if row.get('市场总保费_report', 0) > 0 else 0)

        # 4. 原保费收入增量市场份额
        market_growth = premium_report - premium_base
        total_market_growth = row.get('市场总保费_report', 0) - row.get('市场总保费_base', 0)
        incremental_share = (market_growth / total_market_growth * 100
                             if total_market_growth > 0 else 0)

        # 5. 发展系数
        development_coeff = incremental_share / market_share if market_share > 0 else 0

        # 6. 首年保费与保费收入比
        first_year_ratio = (row.get('首年保费_report', 0) / premium_report * 100
                            if premium_report > 0 else 0)

        # 7. 13个月续保率
        renewal_rate = (row.get('期末保单数_report', 0) / row.get('期初保单数_report', 1) * 100
                        if row.get('期初保单数_report', 0) > 0 else 0)

        # 8. 个人营销渠道的件均保费
        avg_premium_per_policy = (row.get('首年保费_report', 0) / row.get('新单件数_report', 1)
                                  if row.get('新单件数_report', 0) > 0 else 0)

        # 9. 标准保费增长率
        std_premium_base = row.get('标准保费_base', 0)
        std_premium_report = row.get('标准保费_report', 0)
        std_premium_growth = ((std_premium_report - std_premium_base) / std_premium_base * 100
                              if std_premium_base > 0 else 0)

        # 10. 人均保费
        avg_premium_per_sales = (std_premium_report / row.get('营销员数量_report', 1)
                                 if row.get('营销员数量_report', 0) > 0 else 0)

        # 11. 自留保费占净资产比
        net_premium_to_equity = (net_premium_report / row.get('所有者权益_report', 1)) * 100

        results.append({
            '公司': row['公司'],
            '业务线': row['业务线'],
            '原保费收入增长率(%)': round(premium_growth, 2),
            '自留保费增长率(%)': round(net_premium_growth, 2),
            '市场份额(%)': round(market_share, 2),
            '增量市场份额(%)': round(incremental_share, 2),
            '发展系数': round(development_coeff, 2),
            '首年保费占比(%)': round(first_year_ratio, 2),
            '13个月续保率(%)': round(renewal_rate, 2),
            '件均保费': round(avg_premium_per_policy, 2),
            '标准保费增长率(%)': round(std_premium_growth, 2),
            '人均保费': round(avg_premium_per_sales, 2),
            '自留保费净资产比(%)': round(net_premium_to_equity, 2)
        })

    return pd.DataFrame(results)


# 可视化函数
def visualize_metrics(results_df):
    print("生成可视化图表...")

    # 创建图表文件夹
    import os
    folder_name = "insurance_visualizations"
    os.makedirs(folder_name, exist_ok=True)

    # 设置颜色主题
    company_colors = {
        '公司A': '#3498db',
        '公司B': '#2ecc71',
        '公司C': '#e74c3c'
    }

    business_line_colors = {
        '人身险': '#3498db',
        '财险': '#2ecc71',
        '再保人身险': '#e74c3c'
    }

    # 1. 保费增长率对比图
    plt.figure(figsize=(14, 8))
    plt.subplot(1, 2, 1)
    sns.barplot(data=results_df, x='业务线', y='原保费收入增长率(%)', hue='公司', palette=company_colors)
    plt.title('各公司原保费收入增长率对比')
    plt.ylabel('增长率(%)')
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    plt.subplot(1, 2, 2)
    sns.barplot(data=results_df, x='业务线', y='自留保费增长率(%)', hue='公司', palette=company_colors)
    plt.title('各公司自留保费增长率对比')
    plt.ylabel('增长率(%)')
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    plt.tight_layout()
    plt.savefig(f"{folder_name}/1_保费增长率对比.png", dpi=300, bbox_inches='tight')

    # 2. 市场份额分析图
    plt.figure(figsize=(14, 10))
    gs = GridSpec(2, 2, figure=plt.gcf())

    # 市场份额饼图
    ax1 = plt.subplot(gs[0, 0])
    market_share_df = results_df.groupby('公司')['市场份额(%)'].sum().reset_index()
    plt.pie(market_share_df['市场份额(%)'], labels=market_share_df['公司'],
            autopct='%1.1f%%', colors=[company_colors[c] for c in market_share_df['公司']],
            startangle=90, wedgeprops={'edgecolor': 'white', 'linewidth': 1})
    plt.title('总市场份额分布')

    # 增量市场份额堆叠图
    ax2 = plt.subplot(gs[0, 1])
    incremental_share_df = results_df.pivot(index='业务线', columns='公司', values='增量市场份额(%)')
    incremental_share_df.plot(kind='bar', stacked=True, ax=ax2,
                              color=[company_colors[c] for c in incremental_share_df.columns])
    plt.title('增量市场份额分布')
    plt.ylabel('增量市场份额(%)')
    plt.legend(title='公司')
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    # 发展系数热力图
    ax3 = plt.subplot(gs[1, :])
    pivot_df = results_df.pivot(index='公司', columns='业务线', values='发展系数')
    sns.heatmap(pivot_df, annot=True, fmt=".2f", cmap="YlGnBu", ax=ax3, linewidths=0.5)
    plt.title('各公司业务线发展系数热力图')
    plt.ylabel('公司')
    plt.xlabel('业务线')

    plt.tight_layout()
    plt.savefig(f"{folder_name}/2_市场份额分析.png", dpi=300, bbox_inches='tight')

    # 3. 业务质量指标分析
    plt.figure(figsize=(16, 12))

    plt.subplot(2, 2, 1)
    sns.barplot(data=results_df, x='公司', y='首年保费占比(%)', hue='业务线', palette=business_line_colors)
    plt.title('首年保费占比')
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    plt.subplot(2, 2, 2)
    sns.barplot(data=results_df, x='公司', y='13个月续保率(%)', hue='业务线', palette=business_line_colors)
    plt.title('13个月续保率')
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    plt.subplot(2, 2, 3)
    sns.barplot(data=results_df, x='业务线', y='件均保费', hue='公司', palette=company_colors)
    plt.title('件均保费')
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    plt.subplot(2, 2, 4)
    sns.barplot(data=results_df, x='业务线', y='人均保费', hue='公司', palette=company_colors)
    plt.title('人均保费')
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    plt.tight_layout()
    plt.savefig(f"{folder_name}/3_业务质量指标.png", dpi=300, bbox_inches='tight')

    # 4. 自留保费与净资产关系
    plt.figure(figsize=(12, 8))
    sns.scatterplot(data=results_df, x='自留保费净资产比(%)', y='自留保费增长率(%)',
                    hue='公司', size='市场份额(%)', sizes=(50, 300),
                    palette=company_colors, alpha=0.8)

    # 添加参考线
    plt.axvline(x=100, color='r', linestyle='--', alpha=0.5)
    plt.axhline(y=0, color='grey', linestyle='-', alpha=0.5)

    plt.title('自留保费与净资产关系分析')
    plt.xlabel('自留保费占净资产比(%)')
    plt.ylabel('自留保费增长率(%)')
    plt.grid(True, linestyle='--', alpha=0.6)
    plt.legend(title='公司', loc='best')

    plt.tight_layout()
    plt.savefig(f"{folder_name}/4_自留保费与净资产关系.png", dpi=300, bbox_inches='tight')

    # 5. 公司综合指标雷达图
    plt.figure(figsize=(12, 10))
    categories = ['原保费收入增长率(%)', '市场份额(%)', '发展系数',
                  '13个月续保率(%)', '人均保费', '自留保费净资产比(%)']

    # 标准化数据 (0-1范围)
    radar_df = results_df.groupby('公司')[categories].mean().reset_index()
    for col in categories:
        radar_df[col] = (radar_df[col] - radar_df[col].min()) / (radar_df[col].max() - radar_df[col].min())

    N = len(categories)
    angles = [n / float(N) * 2 * np.pi for n in range(N)]
    angles += angles[:1]

    ax = plt.subplot(111, polar=True)
    ax.set_theta_offset(np.pi / 2)
    ax.set_theta_direction(-1)
    plt.xticks(angles[:-1], categories)
    ax.set_rlabel_position(0)
    plt.yticks([0.2, 0.4, 0.6, 0.8], ["0.2", "0.4", "0.6", "0.8"], color="grey", size=7)
    plt.ylim(0, 1)

    for idx, row in radar_df.iterrows():
        values = row[categories].values.flatten().tolist()
        values += values[:1]
        ax.plot(angles, values, linewidth=2, linestyle='solid',
                label=row['公司'], color=company_colors[row['公司']])
        ax.fill(angles, values, alpha=0.1, color=company_colors[row['公司']])

    plt.title('公司综合表现雷达图', size=16, y=1.1)
    plt.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))

    plt.tight_layout()
    plt.savefig(f"{folder_name}/5_公司综合表现雷达图.png", dpi=300, bbox_inches='tight')

    print(f"图表已保存至 {folder_name} 文件夹")


# 主程序
if __name__ == "__main__":
    print("生成模拟数据...")
    mock_data = generate_mock_data()

    print("计算核心指标...")
    results_df = calculate_metrics(mock_data)

    # 生成可视化图表
    visualize_metrics(results_df)

    # 导出结果
    timestamp = datetime.now().strftime("%Y%m%d")
    filename = f"八维保险数据挖掘结果_{timestamp}.xlsx"

    # 将原始数据和计算结果导出到同一个Excel的不同sheet
    with pd.ExcelWriter(filename) as writer:
        mock_data.to_excel(writer, sheet_name='原始数据', index=False)
        results_df.to_excel(writer, sheet_name='指标计算结果', index=False)

    print(f"分析完成! 结果已保存至: {filename}")
    print(f"可视化图表已保存至 insurance_visualizations 文件夹")
    print("\n指标预览:")
    print(results_df.head())